package com.hyjiacan.h2c

import java.time.LocalDateTime
import java.time.format.DateTimeFormatter

object Cmd {
    var url: String = ""
    var user: String = ""
    var pswd: String = ""

    fun parse(args: Array<String>): Boolean {
        if (args.isEmpty()) {
            warn("错误: 缺少参数")
            printHelp()
            return false
        }
        return resolveArgs(args)
    }

    fun printLine() {
        pl("----------------------------------------", false)
    }

    fun info(msg: String, ts: Boolean = true) {
//        pl("\\033[32m$msg\\033[0m")
        pl(msg, ts)
    }

    fun warn(msg: String, ts: Boolean = true) {
//        pl("\\033[32m$msg\\033[0m")
        pl(msg, ts)
    }

    fun error(msg: String, ts: Boolean = true) {
//        pl("\\033[34m$msg\\033[0m")
        pl(msg, ts)
    }

    fun p(msg: String, ts: Boolean = true) {
        if (ts) {
            print("[${timestamp()}] $msg")
        } else {
            print(msg)
        }
    }

    fun pl(msg: String, ts: Boolean = true) {
        if (ts) {
            println("[${timestamp()}] $msg")
        } else {
            println(msg)
        }
    }

    fun pp(msg: String = "") {
        p("h2c> ")
        print(msg)
    }

    fun ppl(msg: String = "") {
        p("h2c> ")
        println(msg)
    }

    fun printResult(result: ExecuteResult) {
        if (!result.success) {
            warn("执行失败\n${result.message}")
            return
        }

        printLine()

        if (result.columns == null) {
            pl("影响行数: ${result.rowsAffected}", false)
            printLine()
            return
        }

        val sizeTable = getCellSize(result)
        val width = sizeTable.sumOf { it } + (result.columns!!.size + 1) + result.columns!!.size * 2

        pl(formatRow(result.columns!!, sizeTable), false)

        pl("-".repeat(width), false)

        var i = 0
        val max = 100
        val iter = result.data!!.iterator()

        i += printLimitResult(iter, sizeTable, max)

        var step = 10
        while (iter.hasNext()) {
            pl("查询结果太多(共 ${result.rowsAffected}) 条，还剩下 ${result.rowsAffected - i}")
            p("按 Enter 查看下 $step 条数据，输入数值可以修改每次查看条数，按 q 停止 [$step]>")
            val count = readln().trim()

            if (count == "q") {
                break
            }
            val temp = count.toIntOrNull()
            if (temp != null) {
                step = temp
            }
            i += printLimitResult(iter, sizeTable, step)
        }

        printLine()
        pl("影响行数: ${result.rowsAffected}", false)
        printLine()
    }

    private fun printLimitResult(iter: Iterator<Array<Any?>>, sizeTable: Array<Int>, limit: Int): Int {
        var i = 0
        while (iter.hasNext() && i < limit) {
            val row = iter.next()
            pl(formatRow(row, sizeTable), false)
            i += 1
        }
        return i
    }

    private fun timestamp(): String {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("HH:mm:ss.SSS"))
    }

    private fun formatRow(row: Array<String>, sizeTable: Array<Int>): String {
        var i = 0
        return "| ${
            row.map { cell ->
                val padded = cell.padEnd(sizeTable[i], ' ')
                i++
                return@map padded
            }.joinToString(" | ")
        } |"
    }

    private fun formatRow(row: Array<Any?>, sizeTable: Array<Int>): String {
        var i = 0
        val x = "| ${
            row.map { cell ->
                val padded = if (cell == null) {
                    "NULL".padEnd(sizeTable[i], ' ')
                } else {
                    cell.toString().padEnd(sizeTable[i], ' ')
                }

                i++
                return@map padded
            }.joinToString(" | ")
        } |"
        return x
    }

    private fun getCellSize(result: ExecuteResult): Array<Int> {
        val sizeTable = result.columns!!.map {
            return@map it.length
        }.toMutableList()

        result.data!!.forEach { row ->
            var idx = 0
            row.forEach { cell ->
                val cellLen = cell?.toString()?.length ?: 4
                if (sizeTable[idx] < cellLen) {
                    sizeTable[idx] = cellLen
                }
                idx++
            }
        }

        return sizeTable.toTypedArray()
    }

    private fun resolveArgs(args: Array<String>): Boolean {
        val parsedArgs = args.map {
            return@map Argument.parse(it)
        }

        parsedArgs.forEach {
            if (it.type == Argument.ArgumentTypes.Value) {
                url = it.value
                if (url.endsWith(".mv.db")) {
                    url = url.substring(0, url.length - 6)
                }
                return@forEach
            }
//            if (it.key == "u") {
//                user = it.value
//                return@forEach
//            }
//            if (it.key == "p") {
//                pswd = it.value
//                return@forEach
//            }
            pl("错误：无效的参数 ${it.key}")
            return false
        }

        return true
    }

    private fun printHelp() {
        printLine()
        pl(
            """
            java -jar h2c <file/url>
            
            file/url        要打开的文件名或URL
            
            注意：所有命令都需要使用 ; 结束。
        """.trimIndent()
        )
    }
}